home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / animutil / cycle / cycle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-24  |  4.7 KB  |  247 lines

  1. /* cycle.c */
  2.  
  3. /* Copyright (c) 1988 David J. Arendash, Inc. */
  4.  
  5. /* This file contains general purpose routines for the handling of
  6.    multiple timer requests useful in applications requiring things like
  7.    color cycling.  The actual color cycle routine I use is include here
  8.    in a comment, as you may want to tailor it for your application.
  9.  
  10.    These routines rely on routines in timer.c, also by me.
  11.  
  12.    You may want to break this file up to library-ize these routines.
  13.  
  14.    Feel free to do anything you want with this stuff.  I only ask that
  15.     1.  Don't delete these comments
  16.     2.  Follow this indentation and punctuation, as it is the least
  17.         annoying and easiest to follow, all pinheads aside.
  18. */
  19.  
  20. #include "exec/types.h"
  21. #include "exec/nodes.h"
  22. #include "exec/lists.h"
  23. #include "exec/memory.h"
  24. #include "exec/interrupts.h"
  25. #include "exec/ports.h"
  26. #include "exec/libraries.h"
  27. #include "exec/tasks.h"
  28. #include "exec/io.h"
  29. #include "exec/devices.h"
  30. #include "devices/timer.h"
  31. #include <stdio.h>
  32.  
  33. /* 4 color cycles in most paint programs */
  34. #define CYCS 4
  35.  
  36. /* used in test routine only */
  37. static char  x[6] = {"0000",13};
  38.  
  39. struct timeval cyc_time[CYCS];
  40. struct IOStdReq *cyc_msg[CYCS], *prototimer;
  41.  
  42. /* keep track of the existance of timer(s) */
  43. char TimerOn = 0;
  44.  
  45. extern struct IOStdReq *CreateTimer();
  46.  
  47. /*
  48.  
  49. This is used for testing
  50.  
  51. main ()
  52. {
  53.    SetCycleTime (3, 3000L);
  54.    SetCycleTime (1, 1500L);
  55.    SetCycleTime (0, 60L);
  56.    SetCycleTime (3, 24L);
  57.  
  58.    if (!SetupCycles())
  59.       exit (0);
  60.  
  61.    StartCycles ();
  62.    while (PerformCycles());
  63.    StopCycles();
  64.    DestroyCycles();
  65. }
  66. */
  67.  
  68. /* sets a timer period based on the (IFF) convention that 16384 = 1/60 sec and
  69.    273 = 1 sec.
  70.    Does not start a timer */
  71.  
  72. SetCycleTime (index, period)
  73. short index;
  74. long  period;
  75. {
  76.     long    t;
  77.  
  78.     t = 273066667 / period;
  79.     cyc_time[index].tv_secs = t / 1000000;
  80.     cyc_time[index].tv_micro = t - (cyc_time[index].tv_secs * 1000000);
  81. }
  82.  
  83. /* Perform one-time initialization for using timers and cycles */
  84. SetupCycles ()
  85. {
  86.     short i;
  87.  
  88.     /* create a prototype timer so we can InitTimerDevice */
  89.     prototimer = CreateTimer ();
  90.     if (prototimer == NULL)
  91.         return (0);
  92.  
  93.      if (!InitTimerDevice (prototimer, (long)UNIT_VBLANK))
  94.         return (0);
  95.  
  96.     /* create timers for cycling based on the prototype timer */
  97.     for (i=0; i < CYCS; i++)
  98.     {
  99.         cyc_msg[i] = CreateTimer();
  100.         DupTimer (prototimer, cyc_msg[i]);
  101.     }
  102. }
  103.  
  104. /* start all timers to get the balls rolling */
  105. StartCycles()
  106. {
  107.     short    i;
  108.  
  109.     for (i=0; i < CYCS; i++)
  110.     {
  111.         QTimer_tv (cyc_msg[i], &cyc_time[i]);
  112.     }
  113.     TimerOn = 1;
  114. }
  115.  
  116. /* Perform the action associated with the timers.
  117.    Call as often as possible (like while waiting for a message). */
  118. PerformCycles ()
  119. {
  120.     short i;
  121.  
  122.     if (!TimerOn)
  123.         return (0);
  124.  
  125.     for (i=0; i < CYCS; i++)
  126.     {
  127.         /* timer ready? */
  128.         if (CheckTimer (cyc_msg[i]))
  129.         {
  130.             /* call the actual "thing-to-do" */
  131.             CycleRange(i);
  132.             /* restart timer */
  133.             QTimer_tv (cyc_msg[i], &cyc_time[i]);
  134.         }
  135.     }
  136.     return (1);
  137. }
  138.  
  139. /* stops all timers */
  140. StopCycles()
  141. {
  142.     short    i;
  143.  
  144.     for (i=0; i < CYCS; i++)
  145.     {
  146.         AbortTimer (cyc_msg[i]);
  147.     }
  148.     TimerOn = 0;
  149. }
  150.  
  151. /* shut down all timer activity */
  152. DestroyCycles ()
  153. {
  154.     short    i;
  155.  
  156.     CloseDevice (prototimer);
  157.     for (i=0; i < CYCS; i++)
  158.     {
  159.         DeleteTimer (cyc_msg[i]);
  160.     }
  161.     DeleteTimer (prototimer);
  162. }
  163.  
  164. /* Do what you want based on the timer.  This is a test routine.  You
  165.    Supply your own */
  166. CycleRange (i)
  167. short i;
  168. {
  169.  
  170.     x[4] = 13;
  171.     x[5] = 0;
  172.  
  173.     if (x[i] == '0')
  174.         x[i] = '1';
  175.     else
  176.         x[i] = '0';
  177.  
  178.     printf ("%s",x);
  179.     fflush (stdout);
  180. }
  181.  
  182. #ifdef DoingItMyWay
  183.  
  184. /* These are the routines I use to perform color cycling.
  185.    It assumes you have an array of shorts containing the color pallet (cmap)
  186.    CRange is an IFF chunk and defined as follows:
  187. struct CRange
  188. {
  189.     WORD    pad1;
  190.     WORD    rate;
  191.     WORD    active;
  192.     UBYTE    low, high;
  193. };
  194.  
  195.    These routines assume (as Deluxe Paint does (in a non-standard way))
  196.    that a cycle is on if the rate is greater than 24 (Hex) and the
  197.    low color is different than the high color.  Had they done it according
  198.    to the IFF spec, active would be non-zero if the range is active.
  199.  
  200. ShiftRange (vp, cmap, range)
  201. struct Viewport *vp;
  202. short *cmap;
  203. struct CRange *range;
  204. {
  205.  
  206.     short i,j;
  207.     long    tcol;
  208.  
  209.     i = range->high;
  210.     j = range->low;
  211.  
  212.     /* 1 if cylcing low to high */
  213.     /* 3 if cycling high to low (backward) */
  214.     if (range->active == 1)
  215.     {
  216.         tcol = cmap[i];
  217.         for (; i > j; i--)
  218.         {
  219.             cmap[i] = cmap[i-1];
  220.         }
  221.         cmap[j] = tcol;
  222.     }
  223.     else if (range->active == 3)
  224.     {
  225.         tcol = cmap[j];
  226.         for (; j < i; j++)
  227.         {
  228.             cmap[j] = cmap[j+1];
  229.         }
  230.         cmap[i] = tcol;
  231.     }
  232.     LoadRGB4 (vp, cmap, (long)range->high);
  233. }
  234.  
  235. CycleRange (index)
  236. short index;
  237. {
  238.     /* only cycle if range is active (according to DPaint) */
  239.     if (ColorRange[index].rate < 0x25)
  240.         return (0);
  241.     if (ColorRange[index].low == ColorRange[index].high)
  242.         return (0);
  243.     ShiftRange (&AppScreen->ViewPort, &new_cmap, &ColorRange[index]);
  244.  
  245. }
  246. #endif
  247.